package com.kancy.swing.demo;

import javax.swing.*;
import java.awt.*;
import java.util.Calendar;

/**
 * @author kancy
 * @date 2020/02/16 19:50
 */
public class Clock extends JComponent implements Runnable {
    /**
     * 半径
     */
    private int radius;
    /**
     * 原点X
     */
    private int centreX;
    /**
     * 原点Y
     */
    private int centreY;

    private JFrame frame;

    public Clock(int radius) {
        this.radius = radius;
        // //构造时钟组件时，开启线程
        new Thread(this).start();
    }
    public Clock(Circle circle) {
    	this.radius = circle.getRadius();
    	this.centreX = (int) circle.getCentre().getX();
    	this.centreY = (int) circle.getCentre().getY();
    	new Thread(this).start();
    }
    public Clock(int centreX,int centreY,int radius) {
    	this.radius = radius;
    	this.centreX = centreX;
    	this.centreY = centreY;
    	new Thread(this).start();
    }
    public Clock(int centreX,int centreY,int radius,JFrame frame) {
    	this.radius = radius;
    	this.centreX = centreX;
    	this.centreY = centreY;
    	this.frame =frame;
    	new Thread(this).start();
    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;

        //这两句话是去除线条锯齿的关键,至于原理笔者也不清楚,这两句是笔者从网络上找来的(就这两句不是自己写的,呵呵)
        g2d.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        //钟盘所在的矩形的左上角的坐标
        int clockPlateX = this.centreX-this.radius;
        int clockPlateY = this.centreY-this.radius;
        //画两个同心圆盘,作为时钟的边框
        g2d.setColor(ClockAttribute.ClockBorderColor);
        g2d.drawOval(clockPlateX, clockPlateY, this.radius * 2, this.radius * 2);
        g2d.drawOval(clockPlateX + 5, clockPlateY + 5, this.radius * 2 - 10, this.radius * 2 - 10);
       
        //圆心坐标
        int centreX = this.centreX;
        int centreY = this.centreY;
        if(centreX==0||centreY==0){
        	centreX=this.radius;
        	centreY=this.radius;
        }
        g2d.setStroke(new BasicStroke(0.8f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));

        //这是钟盘中心的那个点
        g2d.setColor(ClockAttribute.ClockCircleDotColor);
        g2d.fillOval(centreX - 3, centreY - 3, 6, 6);
        g2d.setStroke(new BasicStroke(2.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
        
        
        //以下开始画大刻度,共有12个,表示有12个小时,基准是9时所指的刻度
        double degree = 0;
        double radian = Math.toRadians(degree);
        for (int i = 0; i < 12; ++i) {
        	//计算刻度线相对位置位于左边的点
            int leftX = (int) ((double) centreX - (this.radius - 15) * Math.cos(radian));
            int leftY = (int) ((double) centreY - (this.radius - 15) * Math.sin(radian));
            //计算刻度线相对位置位于右边的点
            int rightX = (int) ((double) centreX - (this.radius - 25) * Math.cos(radian));
            int rightY = (int) ((double) centreY - (this.radius - 25) * Math.sin(radian));

            g2d.setColor(ClockAttribute.ClockMaxKeDuColor);
            g2d.drawLine(leftX, leftY, rightX, rightY);
            
            if(ClockAttribute.ClockHaveNumber){
            	//画表盘数字-从9点开始画
            	g2d.setColor(ClockAttribute.ClockNumberColor);
            	switch (i) {
	            	case 0:g2d.drawString("9", rightX+2, rightY+5);break;
	            	case 1:g2d.drawString("10", rightX+2, rightY+10);break;
	            	case 2:g2d.drawString("11", rightX, rightY+12);break;
	            	case 3:g2d.drawString("12", rightX-6, rightY+13);break;
	            	case 4:g2d.drawString("1", rightX-6, rightY+10);break;
	            	case 5:g2d.drawString("2", rightX-8, rightY+8);break;
	            	case 6:g2d.drawString("3", rightX-8, rightY+5);break;
	            	case 7:g2d.drawString("4", rightX-8, rightY+3);break;
	            	case 8:g2d.drawString("5", rightX-8, rightY+1);break;
	            	case 9:g2d.drawString("6", rightX-3, rightY-2);break;
	            	case 10:g2d.drawString("7", rightX+1, rightY+4);break;
	            	case 11:g2d.drawString("8", rightX+2, rightY+5);break;
            	}
            }
            
            degree += 30;
            //将角度转换为弧度
            radian = Math.toRadians(degree);
        }
        g2d.setStroke(new BasicStroke(1.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
        
        //以下开始画小刻度,共有60-12=48个,基准是0时所指的刻度
        degree = 0;
        radian = Math.toRadians(degree);
        for (int i = 0; i < 60; ++i) {
        	//此条件在于避免小刻度和大刻度重复
            if (i != 0 && degree % 30 != 0) {
                int leftX = (int) ((double) centreX - (this.radius - 15) * Math.cos(radian));
                int leftY = (int) ((double) centreY - (this.radius - 15) * Math.sin(radian));
                int rightX = (int) ((double) centreX - (this.radius - 17) * Math.cos(radian));
                int rightY = (int) ((double) centreY - (this.radius - 17) * Math.sin(radian));
                g2d.setColor(ClockAttribute.ClockMinKeDuColor);
                g2d.drawLine(leftX, leftY, rightX, rightY);
            }
            //每次增加6度
            degree += 360 / 60;
            //将角度转换为弧度
            radian = Math.toRadians(degree);
        }

        //获取当前的时,分,秒(Date类已经被淘汰,这里使用Calendar)
        Calendar cal = Calendar.getInstance();
        int second = cal.get(Calendar.SECOND);
        int minute = cal.get(Calendar.MINUTE);
        int hour = cal.get(Calendar.HOUR_OF_DAY);
        if (hour > 12) {
            hour = hour % 12;
        }
        
        //画中间的数字时间
        String hour_temp=""+hour;
        String minute_temp=""+minute;
        String second_temp=""+second;
        if(hour<10) {
            hour_temp ="0"+ hour;
        }
        if(minute<10) {
            minute_temp ="0"+ minute;
        }
        if(second<10) {
            second_temp ="0"+ second;
        }
        
        g2d.setColor(ClockAttribute.ClockCentreNumberTimeColor);
        g2d.drawString(hour_temp+":"+minute_temp+":"+second_temp, this.centreX-24, this.centreY+15);
        if(frame!=null) {
            frame.setTitle("时钟案例 :"+hour_temp+"点"+minute_temp+"分"+second_temp+"秒");
        }
        //计算秒针当前距离开始位置的弧度,其余两句分别是分针和时针
        double secondProp = Math.toRadians(second * (360 / 60));
        double minuteProp = Math.toRadians(minute * (360 / 60));
        double hourProp = Math.toRadians((hour + minuteProp / (2 * Math.PI)) * (360 / 12));
        //画秒针
        int leftX = (int) (centreX + (this.radius - 25) * Math.sin(secondProp));
        int leftY = (int) (centreY - (this.radius - 25) * Math.cos(secondProp));
        g2d.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
        g2d.setColor(ClockAttribute.ClockSecondSColor);
        g.drawLine(leftX, leftY, centreX, centreY);
        //画分针
        leftX = (int) (centreX + (this.radius - 45) * Math.sin(minuteProp));
        leftY = (int) (centreY - (this.radius - 45) * Math.cos(minuteProp));
        g2d.setStroke(new BasicStroke(1.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
        g2d.setColor(ClockAttribute.ClockMinuteColor);
        g.drawLine(leftX, leftY, centreX, centreY);
        //画时针
        leftX = (int) (centreX + (this.radius - 65) * Math.sin(hourProp));
        leftY = (int) (centreY - (this.radius - 65) * Math.cos(hourProp));
        g2d.setStroke(new BasicStroke(2.5f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
        g2d.setColor(ClockAttribute.ClockHourColor);
        g.drawLine(leftX, leftY, centreX, centreY);
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.repaint();
        }
    }

    private static class Circle {
        private Point centre;
        private int radius;

        public Circle(Point centre, int radius) {
            this.centre = centre;
            this.radius = radius;
        }
        public Circle(int centreX,int centreY, int radius) {
            this.centre = new Point(centreX, centreY);
            this.radius = radius;
        }

        public Point getCentre() {
            return centre;
        }

        public void setCentre(Point centre) {
            this.centre = centre;
        }

        public int getRadius() {
            return this.radius;
        }

        public void setRadius(int radius) {
            this.radius = radius;
        }
    }

    private static class ClockAttribute {
        public static Color ClockBorderColor =Color.GRAY;
        public static Color ClockCircleDotColor =Color.GRAY;
        public static Color ClockMaxKeDuColor =Color.GRAY;
        public static Color ClockMinKeDuColor =Color.GRAY;
        public static Color ClockNumberColor =Color.GRAY;
        public static Color ClockHourColor =Color.GRAY;
        public static Color ClockMinuteColor =Color.GRAY;
        public static Color ClockSecondSColor =Color.GRAY;
        public static Color ClockCentreNumberTimeColor =Color.GRAY;

        public static boolean ClockHaveNumber =true;
    }

}
